package utils

import (
	"encoding/json"
	"fmt"
)

// AuthSerializer provides serialization functionality for authentication data
type AuthSerializer struct{}

// NewAuthSerializer creates a new AuthSerializer instance
func NewAuthSerializer() *AuthSerializer {
	return &AuthSerializer{}
}

// SerializeAuthState serializes an AuthState to JSON bytes
func (as *AuthSerializer) SerializeAuthState(state *AuthState) ([]byte, error) {
	if state == nil {
		return nil, NewAuthError(ErrTypeConfigInvalid, "auth state cannot be nil", "")
	}
	
	data, err := json.Marshal(state)
	if err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to serialize auth state",
			err.Error())
	}
	
	return data, nil
}

// DeserializeAuthState deserializes JSON bytes to an AuthState
func (as *AuthSerializer) DeserializeAuthState(data []byte) (*AuthState, error) {
	if len(data) == 0 {
		return nil, NewAuthError(ErrTypeConfigInvalid, "data cannot be empty", "")
	}
	
	var state AuthState
	if err := json.Unmarshal(data, &state); err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to deserialize auth state",
			err.Error())
	}
	
	// Validate the deserialized state
	if err := state.Validate(); err != nil {
		return nil, err
	}
	
	return &state, nil
}

// SerializeAuthConfig serializes an AuthConfig to JSON bytes
func (as *AuthSerializer) SerializeAuthConfig(config *AuthConfig) ([]byte, error) {
	if config == nil {
		return nil, NewAuthError(ErrTypeConfigInvalid, "auth config cannot be nil", "")
	}
	
	data, err := json.Marshal(config)
	if err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to serialize auth config",
			err.Error())
	}
	
	return data, nil
}

// DeserializeAuthConfig deserializes JSON bytes to an AuthConfig
func (as *AuthSerializer) DeserializeAuthConfig(data []byte) (*AuthConfig, error) {
	if len(data) == 0 {
		return nil, NewAuthError(ErrTypeConfigInvalid, "data cannot be empty", "")
	}
	
	var config AuthConfig
	if err := json.Unmarshal(data, &config); err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to deserialize auth config",
			err.Error())
	}
	
	// Validate the deserialized config
	if err := config.Validate(); err != nil {
		return nil, err
	}
	
	return &config, nil
}

// SerializeSessionAuthData serializes SessionAuthData to JSON bytes
func (as *AuthSerializer) SerializeSessionAuthData(data *SessionAuthData) ([]byte, error) {
	if data == nil {
		return nil, NewAuthError(ErrTypeConfigInvalid, "session auth data cannot be nil", "")
	}
	
	jsonData, err := json.Marshal(data)
	if err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to serialize session auth data",
			err.Error())
	}
	
	return jsonData, nil
}

// DeserializeSessionAuthData deserializes JSON bytes to SessionAuthData
func (as *AuthSerializer) DeserializeSessionAuthData(data []byte) (*SessionAuthData, error) {
	if len(data) == 0 {
		return nil, NewAuthError(ErrTypeConfigInvalid, "data cannot be empty", "")
	}
	
	var sessionData SessionAuthData
	if err := json.Unmarshal(data, &sessionData); err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to deserialize session auth data",
			err.Error())
	}
	
	// Validate all auth states in the session data
	for authType, state := range sessionData.AuthStates {
		if state == nil {
			return nil, NewAuthError(ErrTypeConfigInvalid,
				"auth state cannot be nil",
				fmt.Sprintf("auth type: %s", authType))
		}
		
		if err := state.Validate(); err != nil {
			return nil, NewAuthError(ErrTypeConfigInvalid,
				"invalid auth state in session data",
				fmt.Sprintf("auth type: %s, error: %s", authType, err.Error()))
		}
	}
	
	return &sessionData, nil
}

// SerializeToolAuthMetadata serializes ToolAuthMetadata to JSON bytes
func (as *AuthSerializer) SerializeToolAuthMetadata(metadata *ToolAuthMetadata) ([]byte, error) {
	if metadata == nil {
		return nil, NewAuthError(ErrTypeConfigInvalid, "tool auth metadata cannot be nil", "")
	}
	
	data, err := json.Marshal(metadata)
	if err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to serialize tool auth metadata",
			err.Error())
	}
	
	return data, nil
}

// DeserializeToolAuthMetadata deserializes JSON bytes to ToolAuthMetadata
func (as *AuthSerializer) DeserializeToolAuthMetadata(data []byte) (*ToolAuthMetadata, error) {
	if len(data) == 0 {
		return nil, NewAuthError(ErrTypeConfigInvalid, "data cannot be empty", "")
	}
	
	var metadata ToolAuthMetadata
	if err := json.Unmarshal(data, &metadata); err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to deserialize tool auth metadata",
			err.Error())
	}
	
	// Validate auth config if present
	if metadata.AuthConfig != nil {
		if err := metadata.AuthConfig.Validate(); err != nil {
			return nil, err
		}
	}
	
	return &metadata, nil
}

// SerializeDynamicAuthConfig serializes DynamicAuthConfig to JSON bytes
func (as *AuthSerializer) SerializeDynamicAuthConfig(config *DynamicAuthConfig) ([]byte, error) {
	if config == nil {
		return nil, NewAuthError(ErrTypeConfigInvalid, "dynamic auth config cannot be nil", "")
	}
	
	data, err := json.Marshal(config)
	if err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to serialize dynamic auth config",
			err.Error())
	}
	
	return data, nil
}

// DeserializeDynamicAuthConfig deserializes JSON bytes to DynamicAuthConfig
func (as *AuthSerializer) DeserializeDynamicAuthConfig(data []byte) (*DynamicAuthConfig, error) {
	if len(data) == 0 {
		return nil, NewAuthError(ErrTypeConfigInvalid, "data cannot be empty", "")
	}
	
	var config DynamicAuthConfig
	if err := json.Unmarshal(data, &config); err != nil {
		return nil, NewAuthError(ErrTypeConfigInvalid,
			"failed to deserialize dynamic auth config",
			err.Error())
	}
	
	// Validate the deserialized config
	if err := config.Validate(); err != nil {
		return nil, err
	}
	
	return &config, nil
}

// Ensure AuthSerializer implements the interface
var _ AuthSerializerInterface = (*AuthSerializer)(nil)